import {messages} from "share/common";
import React, { Component, PropTypes } from 'react';
import 'styles/components/template/formula/formula-setting.scss'
import { Input, Modal, Row, Col, Tag, Icon, message } from 'antd'
import FormulaInput from 'components/formula-input'
import deleteIcon from 'images/components/delete.svg'

class FormulaSetting extends Component {

  numberMessageKey = ['number']; //'out_participant_num', 'total_budget' 先只支持messageKey为number
  numberKeyboard = [{
    key: 'clear',
    render: messages('common.clear')/*清空*/
  }, {
    key: 'delete',
    render: <img src={deleteIcon} style={{ verticalAlign: 'text-top' }}/>
  }, '(', ')', '1', '2', '3', '+' , '4', '5', '6', '-', '7', '8', '9', '×', {
    key: '0',
    render: '0',
    col: 12
  }, '.', '÷'];
  keyboardColor = {
    '#FA6478': ['clear'],
    '#1978D2': ['delete', '(', ')', '+', '-', '×', '÷']
  };

  getColor = item => {
    let result = '#4E5B71';
    if(item === '.' || !isNaN(item))
      return result;
    else {
      let key = item.key || item;
      Object.keys(this.keyboardColor).map(color => {
        if(this.keyboardColor[color].indexOf(key) > -1)
          result = color;
      });
      return result;
    }
  };

  state = {
    visible: false,
    factors: [],
    sourceFactors: []
  };

  componentDidMount() {
    const { defaultValue, parseFactor, fields } = this.props;
    if(defaultValue) {
      let factors = parseFactor(defaultValue, fields);
      this.setState({ factors, sourceFactors: factors });
    }
  }

  componentWillReceiveProps(nextProps) {
    const { defaultValue, parseFactor, fields } = nextProps;
    if(defaultValue) {
      let factors = parseFactor(defaultValue, fields);
      this.setState({ factors, sourceFactors: factors });
    } else {
      this.setState({ factors: [], sourceFactors: [] });
    }
  }

  onClickInput = () => {
    const { disabled } = this.props;
    if(!disabled) {
      this.setState({ visible: true });
      this.input.blur();
    }
  };

  onOk = () => {
    const { factors } = this.state;
    const { onChange, formatFactor, testValid, fields } = this.props;
    let formula = factors.map(formatFactor).join('');
    if(testValid(formula, fields, factors)) {
      this.setState({ visible: false, sourceFactors: factors });
      onChange && onChange(formula);
    }
  };

  onCancel = () => {
    const { sourceFactors } = this.state;
    this.setState({ visible: false, factors: sourceFactors });
  };

  onClickKeyboard = key => {
    if(key === 'clear') {
      this.setState({ factors: [] });
      this.formulaInput.setPointerIndex(-1);
    } else if(key === 'delete') {
      const result = this.formulaInput.deleteFactor();
      if(result) {
        this.onDelete(...result);
      }
    } else {
      const [factors, resetPointer] = this.formulaInput.addFactor(key);
      this.setState({ factors }, resetPointer);
    }
  };

  onClickField = field => {
    const [factors, resetPointer] = this.formulaInput.addFactor(field);
    this.setState({ factors }, resetPointer);
  };

  onDelete = (index, resetPointer) => {
    const { factors } = this.state;
    factors.splice(index, 1);
    this.setState({ factors }, resetPointer);
  };

  renderFactor = factor => {
    const { fields } = this.props;
    if(!isNaN(factor) || factor === '.')
      return factor;
    if(typeof factor === 'object') {
      return <span className={this.classNames({
        'formula-setting-modal-input-field': true,
        'formula-setting-modal-input-field-error': !fields.some(field => field.fieldOID === factor.fieldOID)
      })}>{factor.fieldName}</span>;
    } else
      return <span className='formula-setting-modal-input-sign'>{factor}</span>;
  };

  render() {
    const { visible, factors, sourceFactors } = this.state;
    const { disabled, fields, placeholder, formatShowValue } = this.props;
    return (
      <div className="formula-setting">
        <Input
          ref={input => this.input = input}
          onClick={this.onClickInput}
          disabled={disabled}
          value={formatShowValue(sourceFactors)}
          placeholder={placeholder}
        />
        <Modal
          visible={visible}
          title={messages('common-1.key344')/*编辑计算公式*/}
          onOk={this.onOk}
          onCancel={this.onCancel}
          className='formula-setting-modal'
          width={760}
        >
          {visible && (
            <FormulaInput
              factors={factors}
              onRef={ref => this.formulaInput = ref}
              onDelete={this.onDelete}
              renderFactor={this.renderFactor}
            />
          )}
          <div className='formula-setting-modal-info'>
            {messages('common-1.key345')/*编辑计算公式可用来完成审批单内数据的自动结算，例如：采购单内容设置计算公式“合计=单价*数量”，发起人填写单价、数量后，组件将自动计算出合计金额，免手动计算。*/}
          </div>
          <Row>
            <Col span={4}>{messages('common-1.key346')/*计算对象*/}:</Col>
            <Col span={20}>
              {fields.filter(field => this.numberMessageKey.indexOf(field.messageKey) > -1).map(field => (
                <Tag key={field.fieldOID} onClick={() => this.onClickField(field)} style={{ background: '#f8f8f8' }}>{field.fieldName}</Tag>
              ))}
              {fields.filter(field => this.numberMessageKey.indexOf(field.messageKey) > -1).length === 0 && (
                <span style={{color: '#8B93A7'}}>{messages('common-1.key347')/*请先在表单中添加“数字控件”作为计算对象*/}</span>
              )}
            </Col>
            <Col span={4}>{messages('common-1.key348')/*数字键盘*/}:</Col>
            <Col span={20}>
              <Row className='formula-setting-modal-keyboard'>
                {this.numberKeyboard.map(item => <Col
                  span={item.col || 6}
                  key={item.key || item}
                  style={{ color: this.getColor(item) }}
                  className='formula-setting-modal-keyboard-key'
                  onClick={() => this.onClickKeyboard(item.key || item)}
                >
                  {typeof item === 'string' ? item : item.render}
                </Col> )}
              </Row>
            </Col>
          </Row>
        </Modal>
      </div>
    );

  }


  static propTypes = {
    fields: PropTypes.array,
    placeholder: PropTypes.string,
    disabled: PropTypes.bool,
    defaultValue: PropTypes.array,
    onChange: PropTypes.func,
    formatFactor: PropTypes.func,
    parseFactor: PropTypes.func,
    formatShowValue: PropTypes.func,
    testValid: PropTypes.func
  };

  static defaultProps = {
    fields: [],
    placeholder: messages('common-1.key349')/*请点击编辑公式*/,
    formatFactor: factor => {
      return typeof factor === 'object' ? `{${factor.fieldOID}}` : factor
    },
    parseFactor: (value, fields) => {
      let getField = false, fieldOID = '';
      let factors = [];
      Array.prototype.map.call(value, factor => {
        if(!getField) {
          if(factor === '{') {
            getField = true;
          } else {
            factors.push(factor);
          }
        } else {
          if(factor === '}') {
            factors.push(fields.find(field => field.fieldOID === fieldOID));
            getField = false;
            fieldOID = '';
          } else {
            fieldOID += factor;
          }
        }
      });
      return factors;
    },
    formatShowValue: factors => factors.map(factor => factor.fieldName || factor).join(''),
    testValid: (formula, fields) => {
      let hasErrorField = false;
      let target = formula.replace(/\{(\S*?)\}/g, (target, $1) => {
        if(!fields.find(field => field.fieldOID === $1))
          hasErrorField = true;
        return 0;
      });
      target = target.replace(/×/g, '*');
      target = target.replace(/÷/g, '/');
      if(hasErrorField) {
        message.error('公式中含有不存在的表单项，请删除后重试');
        return false;
      }
      try {
        eval(target);
        return true;
      } catch(e) {
        message.error('公式不合法，请检查后重试');
      }
    }
  };

}

export default FormulaSetting;
